from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models import NetworkVolumeAggregate, EvaluationItemScore
from statistics import mean


def _clip(v: float, mx: float) -> float:
    if v < 0:
        return 0.0
    if v > mx:
        return mx
    return v


async def compute_network_volume_scores(session: AsyncSession, evaluation_id: str, code_mapping: dict[str, float]) -> dict:
    result = await session.execute(
        select(NetworkVolumeAggregate).where(NetworkVolumeAggregate.activity_id == code_mapping.get('activity_id'))
    )
    rows = result.scalars().all()
    agg = {x.metric_key: float(x.value or 0) for x in rows}
    scores = map_scores_from_aggregates(agg)
    for code, val in scores.items():
        q = await session.execute(
            select(EvaluationItemScore).where(
                EvaluationItemScore.evaluation_id == evaluation_id,
                EvaluationItemScore.code == code
            )
        )
        row = q.scalars().first()
        if row:
            row.score_value = val
        else:
            session.add(EvaluationItemScore(evaluation_id=evaluation_id, code=code, score_value=val, is_veto=False))
    await session.flush()
    await session.commit()
    return scores


def map_scores_from_aggregates(agg: dict) -> dict:
    media = float(agg.get('media_unique_outlets', 0.0) or 0.0)
    reports = float(agg.get('media_report_count', 0.0) or 0.0)
    social = float(agg.get('social_total_interactions', 0.0) or 0.0)
    growth = float(agg.get('index_growth_rate', 0.0) or 0.0)
    s_0099 = 0.0
    if media >= 6:
        s_0099 = 2.0
    elif media >= 1:
        s_0099 = 1.0
    s_0099 = _clip(s_0099 + min(reports / 50.0, 6.0), 8.0)
    s_009A = 0.5 if social > 0 else 0.0
    if social >= 5000:
        s_009A = 1.0
    s_009A = _clip(s_009A + min(social / 100000.0, 3.0), 4.0)
    s_009B = 0.0
    if growth > 0:
        s_009B = 1.0
    if growth >= 0.2:
        s_009B = 2.0
    s_009B = _clip(s_009B + min(growth * 6.0, 6.0), 8.0)
    return {
        '0099': s_0099,
        '009A': s_009A,
        '009B': s_009B,
    }


def compute_growth_rate_from_series(series: list[dict]) -> float:
    if not series:
        return 0.0
    vals = [float(x.get('value', 0) or 0) for x in series]
    if len(vals) < 3:
        return 0.0
    n = len(vals)
    first = mean(vals[:max(1, n//4)])
    last = mean(vals[-max(1, n//4):])
    if first <= 0:
        return 0.0
    return (last - first) / first
